﻿#ifndef __INC_KSTUB_MATH_H__
#define __INC_KSTUB_MATH_H__

#if _MSC_VER
#pragma once
#endif

// almost function from Patrick Powell's snprintf
// see 'PatrickPowell_snprintf.h'

//
K_INLINE double stub_math_abs(double value)
{
	return (value < 0) ? -value : value;
}

//
K_INLINE double stub_math_pow_10(int exp)
{
	double result = 1;

	while (exp>0)
	{
		result *= 10;
		exp--;
	}

	while (exp < 0)
	{
		result /= 10;
		exp++;
	}

	return result;
}

//
K_INLINE klong stub_math_round(double value)
{
	klong intpart;

	intpart = (klong)value;
	value = value - intpart;

	return value >= 0.5 ? intpart + 1 : intpart;
}

//
K_INLINE klong stub_math_floor(double value)
{
	klong intpart;

	intpart = (klong)value;

	return intpart;
}

//
K_INLINE int stub_math_is_nan(double value)
{
	return value != value;
}

//
K_INLINE int stub_math_is_inf(double value)
{
	return value != 0.0 && value + value == value;
}

//
K_INLINE int stub_math_exponent(double value)
{
	double tmp = value<0.0 ? -value : value;
	int exp = 0;

	while (tmp<1.0 && tmp>0.0 && --exp > -99)
		tmp *= 10;

	while (tmp >= 10.0 && ++exp < 99)
		tmp /= 10;

	return exp;
}

// a replacement for modf that doesn't need the math library. Should be portable, but slow
K_INLINE double stub_math_mod(double x0, double *iptr)
{
#if defined(_INC_MATH) || defined(_MATH_H)
	return modf(x0, iptr);
#else
	int i;
	klong l;
	double x = x0;
	double f = 1.0;

	for (i = 0; i < 100; i++)
	{
		l = (klong)x;
		if (l <= (x + 1) && l >= (x - 1))
			break;
		x *= 0.1;
		f *= 10.0;
	}

	if (i == 100)
	{
		// yikes! the number is beyond what we can handle. What do we do?
		(*iptr) = 0;

		return 0;
	}

	if (i != 0)
	{
		double i2;
		double ret;

		ret = stub_math_mod(x0 - l*f, &i2);
		(*iptr) = l*f + i2;

		return ret;
	}

	(*iptr) = (double)l;

	return x - (*iptr);
#endif
}

//
K_INLINE kulong stub_math_intpart(double value)
{
	kulong res;

	if (value >= K_MAX_ULONG)
		return K_MAX_ULONG;

	res = (kulong)value;

	return res <= value ? res : res - 1;
}

#endif	// __INC_KSTUB_MATH_H__
